home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Programming / ARexxGuide / OS2.x_Version / ARx_IactExamples.rexx < prev    next >
OS/2 REXX Batch file  |  1994-04-02  |  20KB  |  495 lines

  1. /* $VER: 1.2 ARx_IactExamples by Robin Evans (8 Jul 1993,15 Oct 1993,11,20 Mar 1994)
  2. **     v1.1: Added '+' to numbers in Numeric demo to un-exponent them   **
  3. **     v1.2: Added showvalidsymbol which was left out the orig. guide.  */
  4.  
  5. foo = address()
  6. address REXX
  7. call trace 'B'
  8.  
  9. call addlib('rexxsupport.library',0,-30,0)
  10.  
  11.     /* My thanks to Tom Miller on GEnie for pointing out this elegant **
  12.     ** way to redirect output and input to a new window               */
  13.  
  14. arg SubR .
  15.  
  16.     /* set up various formatting codes in compound variables that     **
  17.     ** can be exposed to subroutines by using just the stem           */
  18. csi='9b'x;f.slant=csi'3m'; f.bold=csi'1m'; f.norm=csi'0m'
  19.              f.black=csi'31m'; f.white=csi'32m'; f.blue=csi'33m'
  20.              f.lf = '0a'x; f.cls = csi'0;0H'csi'J'
  21.  
  22. options prompt f.white':::' f.norm
  23.  
  24.     /* Create a new standard-I/O console, so that we can use say      **
  25.     ** and pull instead of writeln() and readln() for output and      **
  26.     ** input. Note: the { system "rx.."} used in the AG link is       **
  27.     ** there because this setup won't work when AG is called by icon  **
  28.     ** unless that kludge is there. Using AG's RX command, the input  **
  29.     ** stream isn't opened under a workbench call                     */
  30. call close STDOUT
  31. if open(STDOUT, "con:98/8/584/345/ARexxGuide Examples/NOCLOSE/SCREEN *", w) then do
  32.     call close STDIN
  33.     call open STDIN, "*", W
  34.     call pragma '*' STDOUT
  35.     call pragma '*' STDIN
  36.         /* for some odd reason, the Amiga shell won't reliably call an  **
  37.         ** external function when at the default Amigaguide address     */
  38.     address REXX
  39.     interpret 'call' SubR 'CLOSE'
  40.     call close STDOUT
  41.     call close STDIN
  42.     call pragma('*')
  43.     return 0
  44.     address
  45. end
  46. else
  47.     signal error
  48.  
  49. SYNTAX:
  50.     ErrCo = rc
  51. ERROR:
  52.     signal off SYNTAX            /* to prevent any possibility of an endless loop */
  53.  
  54.     say '0a'x
  55.     say 'Sorry, an unexpected error has occurred in line' SIGL
  56.     if datatype(ErrCo, 'N') then
  57.     say '      'ErrCo':' errortext(ErrCo)
  58.     call delay(1000)
  59.     push endcli
  60. exit 9
  61.  
  62. /*    $VER: 1.0 ShowNumeric.rexx by Robin Evans (21 May 1993) */
  63.  
  64. ShowNumeric: procedure expose f.
  65.  
  66. /* Demonstrate the effect of different settings of NUMERIC DIGITS
  67. **    and NUMERIC FUZZ
  68. */
  69. arg CLOSE
  70. options failat 21    /* to retain control when an error occurs */
  71. signal on ERROR
  72. signal on SYNTAX
  73.  
  74. say f.white||'   This example will demonstrate how different settings of'
  75. say '   'f.black'NUMERIC DIGITS'f.white 'and' f.black'NUMERIC FUZZ'f.white 'affect the comparison'
  76. say '   of numeric values.'||'0a'x
  77. say '   Enter two numbers separated by at least one space, then'
  78. say '   press <'f.blue||f.bold'Enter'f.norm'>.'
  79. say f.lf||f.black'To quit, press <'f.blue||f.bold'Q'f.norm'> and <'f.blue||f.bold'Enter'f.norm'>.'f.lf
  80.  
  81. do MainLoop = 1        /* exits on the datatype() check 4 lines down */
  82.     say f.lf||f.blue'Enter two numbers to be compared:'
  83.     pull Num.1 Num.2 .
  84.     do i = 1 to 2
  85.             /* any non-numeric value (including null) causes an exit from
  86.             **    the main loop above.
  87.             */
  88.         Num.i = compress(Num.i, ',')
  89.         if ~datatype(Num.i,N) then do
  90.             if ~abbrev(upper(Num.i), 'Q') then do
  91.                 say 'You must enter two numbers.'f.white '   <Enter' f.blue'Q'f.white 'to quit>'f.black
  92.                 iterate MainLoop
  93.             end
  94.             else
  95.                 leave MainLoop
  96.         end
  97.             /* a decimal point is not considered part of a number's length */
  98.         Num.i.len = length(compress(+Num.i,'.'))
  99.     end
  100.     MNum = max(num.1, num.2)
  101.     XLen = max(num.1.len, num.2.len)
  102.     numeric digits min(XLen, 14)
  103.     if XLen > 14 then do
  104.         say f.white'The greatest precision available in ARexx is 14 digits.'
  105.         say 'The number you entered with' XLen 'digits would always'
  106.         say 'be rounded to the closest 14-digit value:'||f.norm
  107.             /*
  108.             **    the prefix + sign causes MNum to be evaluated according to the
  109.             **    current digits() setting
  110.             */
  111.         say '       ' (+MNum) '0a'x
  112.         XLen = 14
  113.     end
  114.     NLen = min(num.1.len, num.2.len)
  115.         /* begin with a setting that will handle the largest number entered */
  116.  
  117.         /* if the numbers are equal under the most precise setting, then
  118.         **    they will be equal under any other setting as well
  119.         */
  120.     if num.1 = num.2 then do
  121.         say (+num.1) 'will always be equal in any comparison to' (+num.2)
  122.         call ShowImprecise
  123.     end
  124.     else do
  125.         numeric fuzz digits() - 1
  126.             /*
  127.                 check for equality under the least precise setting and then
  128.                 find out the most precise setting at which the two are equal
  129.             */
  130.         if num.1 = num.2 then do
  131.         numeric fuzz        /* reset to make the first comparison at 0 */
  132.             do i=0 to XLen-1 while num.1 ~= num.2
  133.                 numeric fuzz i
  134.             end
  135.             if num.1 = num.2 then do
  136.                 say (+num.1) 'is considered equal to' (+num.2) 'under these conditions:'
  137.                 say '   DIGITS setting of' digits()
  138.                 say '   FUZZ   setting of' fuzz()
  139.                 say '   or at a FUZZ setting of 0 and DIGITS setting of' digits() - fuzz()
  140.                 numeric fuzz
  141.                 say f.white'      The following table shows how the numbers are presented'
  142.                 say '      under different settings of NUMERIC DIGITS.'
  143.                 say '      Digits()   'left(Num.1,18)    (Num.2)
  144.                 say f.blue'      ---------  ------------------ ------------------'f.norm
  145.                 do j = max(1,digits()-i) to xlen until strip(MNum) == (+MNum)
  146.                     numeric digits j
  147.                     say '     'center(digits(),11) left((+Num.1),18) (+Num.2)
  148.                 end
  149.             end
  150.         end
  151.         else do
  152.             say max((+num.1), (+num.2)) 'will always be considered greater than' min((+num.1), (+num.2))
  153.             call ShowImprecise
  154.         end
  155.     end
  156.     numeric fuzz
  157.     numeric digits
  158. end
  159. if close = 'CLOSE' then
  160.     push endcli
  161. return 0
  162.  
  163. ShowImprecise:
  164.  
  165.         say f.white'   The following chart shows the two numbers under the'
  166.         say '   most imprecise settings of NUMERIC DIGITS 1 and 2'
  167.         say '   'left(+Num.1,15) (+Num.2)
  168.         say f.blue'    -------------- --------------'f.norm
  169.         numeric fuzz
  170.         numeric digits 1
  171.         say '   'left((+Num.1),15) (+Num.2)
  172.         numeric digits 2
  173.         say '   'left((+Num.1),15) (+Num.2)||f.norm
  174. return
  175.  
  176. /* $VER: 1.1 ShowValidSymbol  (20 Mar 1994) */
  177.  
  178. ShowValidSymbol: procedure expose f.
  179. call addlib('amigaguide.library',-2,-30,0)
  180. if ~loadxref('ARx_Guide.xref') then CheckXR = 0
  181. else CheckXR = 1
  182. LineLen = 62; Tab = 3  /* Values for wordwrap function */
  183. /* Tests whether a value input by the user is a valid symbol */
  184. say WordWrap("This demonstration lets you enter a string of any kind. The",
  185.             "program will tell you if the string could be used as a valid",
  186.             f.white"symbol" f.black"in ARexx. Some symbols can serve as" f.white"variables"f.black"; some",
  187.             "cannot. The program will tell you whether the string you",
  188.             "entered is a" f.white"variable symbol"f.black "or a" f.white"constant"f.black".",,
  189.             LineLen, 6)
  190.  
  191. ValidChars =     xrange('a','z')xrange('A','Z')xrange(0,9)
  192. Info = '0a'x||f.white'Enter a string or press <'f.blue||f.bold'Enter'f.norm||f.white'> alone to quit.'
  193. options Prompt f.white'::: 'f.black
  194. do forever
  195.     Say Info
  196.     pull Resp
  197.     if Resp = '' then leave
  198.     if ~datatype(resp, 'S') then do
  199.         say '0a'x||f.white||Resp f.blue'in not a valid symbol in ARexx'f.black
  200.         BadPos = verify(Resp, ValidChars'$_.!@#')
  201.         say WordWrap("The character at position" BadPos "--"f.bold||f.white||substr(resp,BadPos,1)f.norm"-- in the string is invalid.",
  202.            "Any of the characters `"f.white"a"f.black"' through `"f.white"z"f.black"' or `"f.white"A"f.black"' through `"f.white"Z"f.black"',",
  203.            "or the digits `"f.white"0"f.black"' through `"f.white"9"f.black"' can be used.",
  204.            "You can also use any of these special characters:"f.white "$_!@#"f.black,
  205.            "The period character `"f.white"."f.black"' can be used, but it has special",
  206.            "significance.", LineLen, Tab)
  207.     end
  208.     else do
  209.         say '0a'x||f.white||Resp f.blue'is a valid symbol.'f.black
  210.         select
  211.             when datatype(resp,'N') then do
  212.                 say WordWrap("Since it's a "f.white"number"f.black", it's what is known as a" f.white"constant",
  213.                    "symbol"f.black". This symbol can be used in any" f.white"arithmetic operation"f.black,
  214.                    "but it cannot be used as the target of an" f.white"assignment"f.black".",,
  215.                     LineLen, Tab)
  216.                 if pos('E', resp) > 0 then do
  217.                    numeric digits 14; numeric form scientific; stdnum = (+resp)
  218.                     numeric digits length(compress(left(resp,pos('E', resp)),'E.'))
  219.                     scinum = (+resp)
  220.                    numeric form engineering; engnum = (+resp)
  221.                    if SciNum == StdNum then NumCompare = '.'
  222.                    else if SciNum == EngNum then
  223.                        NumCompare = " or as"f.white SciNum f.black"in both scientific",
  224.                       "and engineering notation."
  225.                    else
  226.                        NumCompare = ", as"f.white SciNum f.black"in scientific",
  227.                       "notation, or as"f.white EngNum f.black"in engineering notation."
  228.                    say WordWrap('0a'x"   The `"f.white"E"f.black"' in this string represents" f.white"exponential notation"f.black".",
  229.                       "The number can be expressed as"f.white StdNum f.black"in the highest",
  230.                       "precision available in ARexx" || NumCompare,,
  231.                       LineLen, Tab)
  232.                    numeric digits; numeric form  scientific
  233.                end
  234.                else do
  235.                    NumLen = length(compress(strip(resp,'L',0),'.'))
  236.                    if NumLen > 9 then do
  237.                        say WordWrap('0a'x"   A" NumLen"-digit number is longer than what can be handled with the",
  238.                           "default 9-digit" f.white"precision"f.black "of ARexx. If this number were used in an",
  239.                           "an arithmetic operation, it would be rounded to" (+Resp)".",,
  240.                            LineLen, Tab)
  241.                        if NumLen > 14 then do
  242.                            numeric digits 14
  243.                            say WordWrap('0a'x"   The maximum precision in ARexx is 14 digits, so the closest value",
  244.                               "that is available is" (+Resp)".", LineLen, Tab)
  245.                        end
  246.                        else do
  247.                            numeric digits NumLen
  248.                            say WordWrap('0a'x"   If the digits setting is increased to" NumLen "with the" f.white"NUMERIC DIGITS"f.black,
  249.                               "instruction, then the number will be expanded to" (+resp)".",,
  250.                               LineLen, Tab)
  251.                        end
  252.                        numeric digits
  253.                    end
  254.                end
  255.             end
  256.             when datatype(left(Resp, 1), 'N') then do
  257.                 say WordWrap("This is a `"f.white"constant symbol"f.black"' because of the digit at the",
  258.                    "beginning. It cannot be used as the target of an",
  259.                    "assignment. Because of the alphabetic characters in",
  260.                    "the symbol, it cannot be used as a" f.white"number"f.black".",
  261.                    "It may, however, be used as the logical "f.slant"<name>"f.norm" of a file",
  262.                    "in OPEN(<name>, <filename>, <opt>).", LineLen, Tab)
  263.                 if pos('.', resp) > 0 then do
  264.                     say WordWrap('0a'x"   Despite the dot -- `.' -- at position" pos('.', resp) "in"f.white Resp||f.black", this",
  265.                        "symbol cannot be used as a"f.white "compound variable"f.black "because",
  266.                        "the"f.white "stem"f.black "of a compound cannot be a" f.white"constant"f.black".",,
  267.                         LineLen, Tab)
  268.                 end
  269.                 else do
  270.                     say WordWrap('0a'x"   It could also be used as a value in the" f.white"tail"f.black "of a",
  271.                       f.white"compound variable"f.black". (Something like" f.white"FOO."resp||f.black".) Using",
  272.                       "a" f.white"constant"f.black "as a tail value assures that another value",
  273.                       "will not be substituted before the variable is evaluated.",,
  274.                       LineLen, Tab)
  275.                 end
  276.             end
  277.             when verify(Resp,    ValidChars'$_!@#') = 0 then do
  278.                     say WordWrap("This is a `"f.white"simple symbol"f.black"' that can be used as the name of",
  279.                        "a "f.white"variable"f.black".", LineLen, Tab)
  280.                         /* Is it a keyword? */
  281.                     if CheckXR then
  282.                         if word(getxref(resp),3) = 2 then do
  283.                             say WordWrap('0a'x||f.white"   "Resp f.black"is an "f.white"instruction keyword" f.black"in ARexx. (See" f.slant"Instruction",
  284.                                "reference"f.norm "for more information.) Despite that, it is not",
  285.                                "reserved and can be used as a"f.white "variable"f.black "in most situations.",,
  286.                                LineLen, Tab)
  287.                         end
  288.                     if find('RESULT RC SIGL', Resp) > 0 then do
  289.                         say WordWrap('0a'x"   "f.white||Resp f.black"is one of three"f.white "special variables"f.black "used by the interpreter.",
  290.                            "Although it can be assigned a value in a script, it is not wise",
  291.                            "to use it that way since the interpreter might change its value.",,
  292.                             LineLen, Tab)
  293.                     end
  294.                 end
  295.             when pos('.', Resp) > 0 then
  296.                 select
  297.                     when left(Resp, 1) = '.' then do
  298.                         say WordWrap("Because of the period at the beginning, this is a "f.white"constant",
  299.                            "symbol"f.black". It cannot be used as the target of an assignment.",
  300.                            "The ANSI REXX committee has warned that symbols like this",
  301.                            "might become invalid in the future.", LineLen, Tab)
  302.                     end
  303.                     when right(resp, 1) == '.' then
  304.                             /* make sure there's not a second period in there */
  305.                         if lastpos('.', Resp, length(Resp) - 1) = 0 & IsVar(resp) then do
  306.                             say WordWrap("This is a `"f.white"stem symbol"f.black"'. It is used as the base upon which a",
  307.                                f.white"compound variable"f.black "can be built, but it can also be used by",
  308.                                "itself in an assignment. If it is, then all compound variables",
  309.                                "built from this stem -- like"f.white resp"1"f.black "-- will be assigned",
  310.                                "the same value as a default value.", LineLen, Tab)
  311.                         end
  312.                         else do
  313.                             say WordWrap("This is a `"f.white"complex symbol"f.black"'. Note that it is not a" f.white"stem" f.black"because",
  314.                                "it contains more that one `.' characters. Only the part of the",
  315.                                "symbol before and including the first period --" f.white || left(resp, pos('.', resp))f.black "--",
  316.                                "is a stem symbol.", LineLen, Tab)
  317.                         end
  318.                     when IsVar(resp) then do
  319.                         parse var Resp stem '.' tail
  320.                         say WordWrap("This is a `"f.white"complex symbol"f.black"'. The `"f.white||stem"."f.black"' part of the symbol",
  321.                                  "is called the `"f.white"stem"f.black"'. The rest of it, `"f.white||tail||f.black"', is called",
  322.                                  "the `"f.white"tail"f.black"'. If any simple symbol in the tail is assigned a",
  323.                                  "value, then that value is substituted when the variable",
  324.                                  "named by this symbol is evaluated in an expression.",,
  325.                                  LineLen,Tab)
  326.  
  327.                     end
  328.                     otherwise
  329.                         say "   This is a" f.white"constant symbol"f.black". It cannot be assigned a value."
  330.                 end
  331.             otherwise NOP
  332.         end
  333.     end
  334. end
  335. call remlib('amigaguide.library')
  336. return 0
  337.  
  338. IsVar:
  339.    /* call trace b */
  340.    return symbol(arg(1)) ~== 'BAD' & (datatype(left(arg(1),1), m),
  341.                                      | verify(left(arg(1),1), '!$_@#', M))
  342.  
  343.  WordWrap: procedure
  344.    /* Arguments:                                                        **
  345.    ** Text       := The string that is to be split into parts           **
  346.    ** Length     := Maximum length of lines desired.                    **
  347.    ** Tab        := White space to add at start of line                 */
  348.    parse arg Text, Length, Tab
  349.  
  350.    Line. = ''                            /* All compounds are now null  */
  351.    EndPos = length(Text); DivPos = 1     /* Preliminary values for loop */
  352.    numeric digits
  353.    Length = Length - Tab    /* shorten it to allow for the tab           */
  354.    Line = ''; csi = '9b'x
  355.    do i = 1 while EndPos <= length(Text)
  356.            /* Get a rough count of control characters in the line        */
  357.        FmtChar = CountChar(csi, substr(Text, DivPos, Length + 12))*4
  358.       EndPos = lastpos(' ',Text' ', DivPos + FmtChar + Length+1)
  359.          /* Handle a word that's bigger than the line length by         **
  360.          ** splitting it arbitrarily at the line length                 */
  361.       if EndPos < DivPos then do
  362.          EndPos = DivPos + Length - 1
  363.          Text = insert('- ', Text, EndPos-2)
  364.       end
  365.       Line = Line || copies(' ', Tab)substr(Text, DivPos, EndPos-DivPos)'0a'x
  366.          /* Add one to DivPos because we want to get rid of the space   **
  367.          ** at the start of each line.                                  */
  368.       DivPos = EndPos + 1
  369.    end
  370.    return strip(Line,'t', '0a'x)
  371.  
  372. CountChar:
  373.    return length(arg(2)) - length(compress(arg(2), arg(1)))
  374.  
  375.  
  376.  
  377.  
  378. /*    $VER: 1.0 ShowSTDIO.rexx by Robin Evans (11 Jun 1993) */
  379.  
  380. ShowSTDIO: procedure expose f.
  381.  
  382. /* Demonstrate the effect of redirected IO. */
  383.  
  384. arg CLOSE
  385. options failat 21    /* to retain control when an error occurs */
  386. signal on ERROR
  387. signal on SYNTAX
  388.  
  389. LFS = f.lf||f.white
  390.  
  391. do forever        /* Loop allows reentering the demonstration */
  392.     say f.white||f.cls
  393.     say '      This demonstration will write a small ARexx file to the t:'
  394.     say '      directory.'
  395.     say
  396.     say '      That file will be called with various forms of' f.black'redirection'f.white
  397.     say '      to demonstrate the effect of redirection characters on '
  398.     say '      ARexx files.'f.norm
  399.  
  400.         /* Save the demo file to the ram: disk T: directory */
  401.     TFName = 't:testIO.rexx'
  402.     TestCode = '/**/'f.lf'options prompt "0a"x||"Enter any text then press <Enter>: "'f.lf'pull T$'f.lf'say "0a"x||"You entered:" T$'f.lf
  403.     if open(TFile, TFName, w) then do
  404.         call writech(TFile, TestCode)
  405.         call close TFile
  406.         if QKey() then return 0
  407.         say LFS'The file has been written to the T: directory:'
  408.         call showSPrompt('list' left(TFName, 5)'#?')
  409.         call showSPrompt( 'type' TFname)
  410.         if QKey() then return 0
  411.         say f.lf LFS'We will now run that program. Enter some text when prompted:'
  412.         call showSPrompt('rx' TFname)
  413.         say LFS'Notice that the program output to the shell the text you entered.'
  414.         if QKey() then return 0
  415.         say LFS'We''ll run it again, but this time we''ll redirect output using'
  416.         say '   the DOS ">" redirection operator.'
  417.         call showSPrompt('rx' TFname '>T:IOutput')
  418.         say LFS'Notice that the program didn''t output anything this time, even'
  419.         say '   though the SAY instruction is still in the program.'
  420.         say '   What happened? Observe:'
  421.         call showSPrompt('type T:IOutput')
  422.         say LFS'Because of the redirection operator, the output of SAY went to a'
  423.         say '   file instead of to the screen.'
  424.         if QKey() then return 0
  425.         say LFS'What happens when both input and output are redirected?'
  426.         call showSPrompt('rx' TFname '<'TFName '>T:IOutput')
  427.         say LFS'There was no prompt this time because the PULL instruction was'
  428.         say '   redirected to look for its input from the file "'TFName'".'
  429.         say '   It pulled the first line from that file:'
  430.         call showSPrompt('type T:IOutput')
  431.     end
  432.     say f.lf||f.white||f.slant'This concludes the demonstration.'f.norm
  433.     say '   Press <'f.white||f.bold'Enter'f.norm'> to quit or <'f.white||f.bold'R'f.norm'> and <'f.white||f.bold'Enter'f.norm'> to repeat the demo.'
  434.     pull Rsp
  435.     if Rsp ~= 'R' then leave
  436. end
  437. return 0
  438.  
  439. QKey: procedure expose f.
  440.     options prompt f.lf||f.blue'   Type <Q> and <Enter> to quit. Press <Enter> alone to continue.'f.norm
  441.     pull QKey
  442.     if QKEY = Q then return 1
  443.     else return 0
  444.  
  445. ShowSPrompt: procedure expose f.
  446.     address command
  447.     parse arg DCmd
  448.     call writech(STDOUT, f.lf||f.blue'Shell'f.white'> 'f.norm)
  449.     call delay(30)
  450.     say DCmd
  451.     ""DCmd
  452. return 0
  453.  
  454. DoBreak: procedure expose f.
  455.       /* Show how the break keys work in a subroutine */
  456.         signal off break_e
  457.       Say f.white" Press Control and E to stop the obnoxious listing that"
  458.       say " will follow this message."f.black
  459.       if QKey() then return
  460.       NumRepeats = AdInfinit()
  461.       say f.white||f.lf'The message was repeated' NumRepeats 'times.'
  462.       say f.lf'We have returned from a subroutine to the main code of'
  463.       say 'the program. The break key was detected within the subroutine'
  464.       say 'but control could still be returned to the main program.'
  465.       say f.lf||f.white'   This demo is coded in the file' f.blue'ARx_IactExamples.rexx'
  466.       say f.white'   in the subroutine' f.blue'DoBreak:'
  467.       say f.black||f.lf'- Press any key - '
  468.       pull .
  469.       return
  470.  
  471.          /* The subroutine being called by SIGNAL can be anywhere in **
  472.          ** program. PROCEDURE¤¤, used in AdInfinit blinds it to     **
  473.          ** variables in the main program, but still allows the      **
  474.          ** BREAK_E subroutine to retrieve the [Rep] variable.       */
  475.  
  476.       BREAK_E:
  477.          say f.blue'Break detected at line' SIGL':'
  478.          say f.white||sourceline(SIGL)
  479.          return Rep
  480.  
  481.       AdInfinit: PROCEDURE expose f.
  482.             /* turning on the signal within the subroutine¤¤ means    **
  483.             ** it will be effective only while this subroutine is     **
  484.             ** active                                                 */
  485.          signal on break_e
  486.          do Rep = 1
  487.             say 'Press Ctrl-E at any time.'
  488.             call delay 25
  489.             say 'Stop me. Please.'
  490.          end
  491.             /* because the loop¤¤ above is endless, this RETURN¤¤     **
  492.             ** will never be reached.                                 */
  493.          return 0
  494.  
  495.